//################################################################################
// MIT License
// Copyright (c) 2024 ZhangYihua
//
// Change Logs:
// Date           Author       Notes
// 2020-10-03     ZhangYihua   first version
//
// Description  : Double Page Buffer
//################################################################################

module dpb_ctrl #(
parameter           PAGE_SIZE               = 32,
parameter           ADRCMPS_EN              = 1'b1,     // compress address hole for area saving
//parameter           ADRCMPS_EN              = 1'b0,     // not compress address hole for timing

// the following parameters are calculated automatically
parameter           OFST_BW                 = $clog2(PAGE_SIZE),
parameter           ADDR_BW                 = OFST_BW+1
) ( 
input                                       rst_n,
input                                       clk,

input                                       dpw_done,   // write a page done
input               [OFST_BW-1:0]           dpw_ofst,   // offset inside a page
output  reg                                 dpw_full,   // two page is done
output  reg                                 dpw_page,
output              [ADDR_BW-1:0]           dpw_addr,

input                                       dpr_done,   // read a page done
input               [OFST_BW-1:0]           dpr_ofst,   // offset inside a page
output  reg                                 dpr_empty,  // not any page is done
output  reg                                 dpr_page,
output              [ADDR_BW-1:0]           dpr_addr
);

//################################################################################
// define local varialbe and localparam
//################################################################################


//################################################################################
// main
//################################################################################

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        dpw_page <=`U_DLY 1'b0;
    end else begin
        if (dpw_done==1'b1)
            dpw_page <=`U_DLY ~dpw_page;
        else
            ;
    end
end

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        dpr_page <=`U_DLY 1'b0;
    end else begin
        if (dpr_done==1'b1)
            dpr_page <=`U_DLY ~dpr_page;
        else
            ;
    end
end

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        dpr_empty <=`U_DLY 1'b1;
    end else begin
        if (dpw_done==1'b1)
            dpr_empty <=`U_DLY 1'b0;
        else if ((dpr_done==1'b1) && (dpr_page!=dpw_page))
            dpr_empty <=`U_DLY 1'b1;
        else if (dpr_page!=dpw_page)
            dpr_empty <=`U_DLY 1'b0;
        else if (dpw_full==dpr_empty)
            dpr_empty <=`U_DLY 1'b1;
        else
            ;
    end
end

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        dpw_full <=`U_DLY 1'b0;
    end else begin
        if (dpr_done==1'b1)
            dpw_full <=`U_DLY 1'b0;
        else if ((dpw_done==1'b1) && (dpr_page!=dpw_page))
            dpw_full <=`U_DLY 1'b1;
        else if (dpr_page!=dpw_page)
            dpw_full <=`U_DLY 1'b0;
        else if (dpw_full==dpr_empty)
            dpw_full <=`U_DLY 1'b0;
        else
            ;
    end
end

generate if (ADRCMPS_EN==1'b1) begin:G_CMPS
    localparam [ADDR_BW-1:0]    PAGE_SIZE_V     = PAGE_SIZE;

    assign dpw_addr = dpw_page*PAGE_SIZE_V + dpw_ofst;
    assign dpr_addr = dpr_page*PAGE_SIZE_V + dpr_ofst;
end else begin:G_NCMPS
    assign dpw_addr = {dpw_page, dpw_ofst};
    assign dpr_addr = {dpr_page, dpr_ofst};
end endgenerate

//################################################################################
// ASSERTION
//################################################################################

`ifdef CBB_ASSERT_ON
// synopsys translate_off


// synopsys translate_on
`endif

endmodule
